package com.dhcc.bpm.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.*;
import java.util.regex.Pattern;

public class YamlUtils {
    private static final Logger log = LoggerFactory.getLogger(YamlUtils.class);

    /**
     * 获取json并生成yaml
     */
    public static void readJsonAndCreateYaml(String json_url, String yaml_url) {
        try {
            String param = readJson(json_url);
            createYaml(yaml_url, param);
        } catch (Exception e) {
            log.error("异常信息：{}", e);
        }
    }

    /**
     * 将json转化为yaml格式并生成yaml文件
     *
     * @param jsonString
     * @return
     * @throws JsonProcessingException
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    public static void createYaml(String yaml_url, String jsonString) throws JsonProcessingException, IOException {
        // parse JSON
        JsonNode jsonNodeTree = new ObjectMapper().readTree(jsonString);
        // save it as YAML
        String jsonAsYaml = new YAMLMapper().writeValueAsString(jsonNodeTree);

        Yaml yaml = new Yaml();
        Map<String, Object> map = (Map<String, Object>) yaml.load(jsonAsYaml);

        createYamlFile(yaml_url, map);
    }

    /**
     * 将数据写入yaml文件
     *
     * @param url  yaml文件路径
     * @param data 需要写入的数据
     */
    public static void createYamlFile(String url, Map<String, Object> data) {
        Yaml yaml = new Yaml();
        FileWriter writer = null;
        try {
            writer = new FileWriter(url);
            yaml.dump(data, writer);
        } catch (IOException e) {
            log.error("异常信息：{}", e);
        }finally {
            if(writer != null){
                try {
                    writer.close();
                }catch (IOException e){
                    log.error("异常信息：{}", e);
                }
            }
        }
    }

    /**
     * 读取json文件并返回字符串
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static String readJson(String url) throws Exception {
        File file = new File(url);
        FileReader fileReader = new FileReader(file);
        try(BufferedReader bufReader = new BufferedReader(fileReader)) {
            String message = new String();
            String line = null;
            while ((line = bufReader.readLine()) != null) {
                message += line;
            }
            return message;
        }catch ( IOException e){
            log.error("异常信息：{}", e);
        }finally {
            if(fileReader != null){
                try {
                    fileReader.close();
                }catch (IOException e){
                    log.error("异常信息：{}", e);
                }
            }
        }
        return null;
    }

    /**
     * 方法一
     * <p>
     * 读取yaml生成Map并返回
     *
     * @return
     */
    public static Map<String, Object> yamlToMap(String yaml_url) {
        Map<String, Object> loaded = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(yaml_url);
            Yaml yaml = new Yaml();
            loaded = (Map<String, Object>) yaml.load(fis);
        } catch (FileNotFoundException ex) {
            log.error("异常信息：{}", ex);
        }finally {
            if(fis!=null){
                try {
                    fis.close();
                }catch (IOException e){
                    log.error("异常信息：{}", e);
                }
            }
        }
        return loaded;
    }

    /**
     * 方法二
     * <p>
     * 读取yaml的内容并转为map
     *
     * @return
     */
    public static Map returnMapFromYaml(String yaml_url) {
        YamlReader reader = null;
        Object object = null;
        Map map = null;
        try {
            reader = new YamlReader(new FileReader(yaml_url));
            object = reader.read();
            map = (Map) object;
        } catch (FileNotFoundException e) {
            log.error("异常信息：{}", e);
        } catch (YamlException e) {
            log.error("异常信息：{}", e);
        }finally {
            if(reader!=null){
                try {
                    reader.close();
                }catch (IOException e){
                    log.error("异常信息：{}", e);
                }
            }
        }
        return map;
    }

    /**
     * 读取yaml生成json并返回
     *
     * @param file
     * @return
     */
    @SuppressWarnings("unchecked")
    public static String yamlToJson(String file) {
        Gson gs = new Gson();
        Map<String, Object> loaded = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            Yaml yaml = new Yaml();
            loaded = (Map<String, Object>) yaml.load(fis);
        } catch (FileNotFoundException ex) {
            log.error("异常信息：{}", ex);
        }finally {
            if(fis!=null){
                try {
                    fis.close();
                }catch (IOException e){
                    log.error("异常信息：{}", e);
                }
            }
        }
        return gs.toJson(loaded);
    }

    public static Map<String, Object> getMapArgs(String yml) {
        Yaml yaml = new Yaml();
        Map<String, Object> application = (Map) yaml.load(yml);
        Map<String, Object> map = new HashMap<>();
        getMapArgs(application, "", map);
        return map;
    }


    //递归找出jar的配置项
    public static void getMapArgs(Map<String, Object> map, String keys, Map<String, Object> maps) {
        for (String key : map.keySet()) {
            Object value = map.get(key);
            if (!StringUtils.isBlank(keys)) {
                key = keys + "." + key;
            }
            if (value == null) {
                continue;
            }
            if (LinkedHashMap.class.getName().equals(value.getClass().getName()))
                getMapArgs((Map<String, Object>) value, key, maps);
            else {
                maps.put(key, value);
            }

        }
    }


    public static String keyValueToYml(Map<String, Object> map) {
        Map<Integer, Object> n = new HashMap<>();
        for (int k = 0; k < Integer.MAX_VALUE; k++) {
            Map<String, Set<String>> treeMap = new HashMap<>();
            int q = 0, j = 0;
            for (String key : map.keySet()) {
                j++;
                String[] keys = key.split("\\.");
                if (keys.length <= k) {
                    q++;
                    continue;
                }
                Set<String> keyList = treeMap.get(keys[k]);
                if (keyList != null) {
                    keyList.add(key);
                } else {
                    keyList = new TreeSet<>();
                    keyList.add(key);
                }
                treeMap.put(keys[k], keyList);
            }
            n.put(k, treeMap);

            if (q == j) {
                break;
            }

        }
        System.out.println(n + "------");
        Map<String, Object> linkedHashMap = new HashMap<>();
        for (int k : n.keySet()) {
            Map<String, Set<String>> setLinkedHashMap = (HashMap<String, Set<String>>) n.get(k);
            for (String key : setLinkedHashMap.keySet()) {
                Set<String> set = setLinkedHashMap.get(key);
                if (k == 0) {
                    if (set.size() == 1 && key.equals(set.iterator().next())) {
                        linkedHashMap.put(key, map.get(key));
                    } else {
                        linkedHashMap.put(key, new HashMap<>());
                    }
                } else {
                    Iterator<String> iterator = set.iterator();
                    while (iterator.hasNext()) {
                        Map<String, Object> linked = linkedHashMap;
                        String value = iterator.next();
                        String[] ele = value.split("\\.");
                        int x = k;
                        while (k - x < k) {
                            if (linked.get(ele[k - x]) == null) {
                                linked = new HashMap<>();
                            } else {
                                linked = (HashMap<String, Object>) linked.get(ele[k - x]);
                            }
                            x--;
                        }
                        if (key.equals(ele[k]) && k == ele.length - 1) {
                            linked.put(key, map.get(value));
                        } else {
                            linked.put(key, new HashMap<>());
                        }

                        x = k;
                        for (int i = 0; i < k; i++) {

                            Map<String, Object> link = linkedHashMap;
                            if (k == 3) {
                                System.out.println(link + ".........");
                            }

                            int q = -1;
                            while (x > 1 && x - q > 2 + i) {
                                q++;
                                System.out.println(link + "[[[[[[");
                                System.out.println(ele[q]);
                                link = (Map<String, Object>) link.get(ele[q].trim());
                                if (k == 3) {
                                    System.out.println(link + "----");
                                }
                            }
                            if (k == 3) {
                                System.out.println(linked + "ooooo" + ele[k - i - 1]);
                            }
                            link.put(ele[k - i - 1], linked);

                            if (k == 3) {
                                System.out.println(link + "+++++");
                            }

                            linked = link;
                        }
                        linkedHashMap = linked;
                    }
                }


            }


        }

        return JSONObject.toJSONString(linkedHashMap);
    }

}